

import UIKit
import AuthenticationServices
import RxSwift

public protocol PlatformLoginDelegate:NSObjectProtocol{
    func login(plat:LoginPlatform)
    func observerLoginProgress(progress:LoginProgress)
//    func beginLogin(plat:LoginPlatform)
//    func loginSuccess(plat:LoginPlatform,userInfo:BasePlatformUserInfo)
//    func loginFailed(plat:LoginPlatform,message:String,isCanled:Bool)
}

public struct BasePlatformUserInfo {
    public var openID:String = ""
    public var accessToken = ""
    public var nickName = ""
    public var userHead = ""
    public var sex = SexType.男
    public var info:NSMutableDictionary = NSMutableDictionary()
    
    public var plat = LoginPlatform.wx
    public init(openID:String,accessToken:String,nickName:String,userHead:String,sex:SexType,info:NSMutableDictionary) {
        self.openID = openID
        self.accessToken = accessToken
        self.nickName = nickName
        self.userHead = userHead
        self.info = info
    }
    
    public var requestParams:[String:Any]{
        get{
            var params = [String:Any]()
            params["openid"] = self.openID
            params["nickname"] = self.nickName
            params["avatar"] = self.userHead
            params["gender"] = self.sex.rawValue
            params["plat_type"] = plat.ID
            return params
        }
    }
    
    public init() {
        
    }
}

public enum LoginResult {
    case success(LoginPlatform,userInfo:BasePlatformUserInfo)
    case canle(LoginPlatform)
    case err(LoginPlatform,err:String)
}

public enum LoginProgress {
    case beginLogin(LoginPlatform)
    case finishLogin(LoginResult)
    case beginGetUserInfo(LoginPlatform)
    case finishGetUserInfo(LoginResult)
}


public class LoginSDK:NSObject,PlatformLoginDelegate{
    public func observerLoginProgress(progress: LoginProgress) {
        self.progress.onNext(progress)
        self.changeProgress(progress)
    }
    
    public static var shared:LoginSDK = LoginSDK()
    public var changeProgress:(LoginProgress)->Void = {_ in}
    
    public let progress:PublishSubject<LoginProgress> = PublishSubject<LoginProgress>()
    
    public func login(plat: LoginPlatform) {
        plat.engine.delegate = self
        plat.engine.login()
    }
 
    
}


public protocol LoginEngine:NSObjectProtocol{
    func login()
    var platform:LoginPlatform {get}
    var delegate:PlatformLoginDelegate? {get set}
    var ID:String{get set}
}

public class LoginManager{
    public static let shared = LoginManager()
    public var engines:[LoginEngine] = []
    
    public func add(engine:LoginEngine) {
        var have = false
        for r in engines {
            if r.ID == engine.ID{
                have = true
            }
        }
        if !have{
            engines.append(engine)
        }
    }
    public func getEngine(ID:String) -> LoginEngine {
        for e in engines {
            if e.platform.ID == ID{
                return e
            }
        }
        return AppleLoginEngine.shared
    }
}


public enum LoginPlatform:String{
    case wx = "微信"
    case qq = "QQ"
    case sina = "新浪"
    case apple = "Apple"
    
    
    public var ID:String{
        switch self {
        case .qq:
            return "qq"
        case .sina:
            return "sina"
        case .apple:
            return "apple"
        default:
            return "wechat"
        }
    }
    
    public var engine:LoginEngine
    {
        return LoginManager.shared.getEngine(ID: ID)
    }
    
    
    public var platformName:String{
        get{
            switch self {
            case .wx:
                return "微信"
            case .qq:
                return "QQ"
            case .apple:
                return "Apple"
            default:
                return "新浪"
            }
        }
    }
    
    public var authedUser:[String:Any]{
        get{
            switch self {
            case .qq:
                return ["platform":"QQ"]
            case .sina:
                return ["platform":"sina"]
            default:
                return ["platform":"wx"]
            }
        }
    }
}



class AppleLoginEngine:NSObject,LoginEngine,ASAuthorizationControllerPresentationContextProviding,ASAuthorizationControllerDelegate{
    lazy var ID:String = {return LoginPlatform.apple.rawValue}()
    
    var platform: LoginPlatform {
        get{
            return LoginPlatform.apple
        }
    }
    
    var delegate: PlatformLoginDelegate?
    static var shared = AppleLoginEngine()
    
    func postGetUserInfoFiailed(msg:String) {
        let result = LoginResult.err(platform, err: msg)
        let progress = LoginProgress.finishGetUserInfo(result)
        self.delegate?.observerLoginProgress(progress: progress)
    }
    

    
    func login()
    {
      
            
        if #available(iOS 13.0, *) {
            // 基于用户的Apple ID授权用户，生成用户授权请求的一种机制
            let appleIDProvide = ASAuthorizationAppleIDProvider()
            // 授权请求AppleID
            let appIDRequest = appleIDProvide.createRequest()
            // 在用户授权期间请求的联系信息
            appIDRequest.requestedScopes = [ASAuthorization.Scope.fullName,ASAuthorization.Scope.email]
            // 由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器
            let authorizationController = ASAuthorizationController.init(authorizationRequests: [appIDRequest])
            // 设置授权控制器通知授权请求的成功与失败的代理
            authorizationController.delegate = self
            // 设置提供 展示上下文的代理，在这个上下文中 系统可以展示授权界面给用户
            authorizationController.presentationContextProvider = self
                      // 在控制器初始化期间启动授权流
            authorizationController.performRequests()
        }
            
        
        
    }
    

    @available(iOS 13.0, *)
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
//告诉苹果弹窗到哪个window上
        return UIApplication.shared.windows.last ?? ASPresentationAnchor()
    }
    
    
    @available(iOS 13.0, *)
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if authorization.credential.isKind(of: ASAuthorizationAppleIDCredential.classForCoder()) {
                  // 用户登录使用ASAuthorizationAppleIDCredential
                  let appleIDCredential = authorization.credential as! ASAuthorizationAppleIDCredential
//                  let user = appleIDCredential.user
//                  // 使用过授权的，可能获取不到以下三个参数
//                  let familyName = appleIDCredential.fullName?.familyName ?? ""
//                  let givenName = appleIDCredential.fullName?.givenName ?? ""
//                  let email = appleIDCredential.email ?? ""
//
                  let identityToken = appleIDCredential.identityToken ?? Data()
//                  let authorizationCode = appleIDCredential.authorizationCode ?? Data()
//                  // 用于判断当前登录的苹果账号是否是一个真实用户，取值有：unsupported、unknown、likelyReal
//                  let realUserStatus = appleIDCredential.realUserStatus
                
                    print(String(data: identityToken, encoding: .utf8)!)
                  // 服务器验证需要使用的参数
                    loginWithServer(String(data: identityToken, encoding: .utf8)!)
            
              }
//                else if authorization.credential.isKind(of: ASPasswordCredential.classForCoder()) {
//                  // 这个获取的是iCloud记录的账号密码，需要输入框支持iOS 12 记录账号密码的新特性，如果不支持，可以忽略
//                  // Sign in using an existing iCloud Keychain credential.
//                  // 用户登录使用现有的密码凭证
//                  let passworCreddential = authorization.credential as! ASPasswordCredential
//                  // 密码凭证对象的用户标识 用户的唯一标识
//                  let user = passworCreddential.user
//                  // 密码凭证对象的密码
//                  let password = passworCreddential.password
//              }
                else{
                  // "授权信息不符合"
              }
    }
    
    private func loginWithServer(_ token:String) {
    
    }
        
    @available(iOS 13.0, *)
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        var errorStr = ""
        switch (error as NSError).code {
                case ASAuthorizationError.canceled.rawValue :
                    errorStr = "用户取消了授权请求"
                case ASAuthorizationError.failed.rawValue :
                    errorStr = "授权请求失败"
                case ASAuthorizationError.invalidResponse.rawValue :
                    errorStr = "授权请求无响应"
                case ASAuthorizationError.notHandled.rawValue :
                    errorStr = "未能处理授权请求"
                case ASAuthorizationError.unknown.rawValue :
                    errorStr = "授权请求失败原因未知"
                default:
                    break
        }
        postLoginFiailed(msg:(errorStr))
    }
    
    func postLoginFiailed(msg:String) {
        let result = LoginResult.err(platform, err: msg)
        let progress = LoginProgress.finishLogin(result)
        self.delegate?.observerLoginProgress(progress: progress)
    }
    
   
    
}

